<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3D Heart Particle Animation</title>
    <style>
        body, html {
            margin: 0;
            padding: 0;
            overflow: hidden;
            background-color: black;
        }
        canvas {
            display: block;
        }
    </style>
</head>
<body>
    <canvas id="canvas"></canvas>
    <script>
        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext('2d');
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;

        const particles = [];
        const particleCount = 5000;
        let angle = 0;
        let startTime = null;
        const transitionDuration = 2000; // 2 seconds

        function heart3D(t, u) {
            const x = 16 * Math.pow(Math.sin(t), 3);
            const y = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t);
            const z = (u - 0.5) * 20;  // 使用u随机分布粒子以增加立体效果
            return { x, y, z };
        }

        for (let i = 0; i < particleCount; i++) {
            const t = Math.random() * Math.PI * 2;
            const u = Math.random();
            const { x, y, z } = heart3D(t, u);
            particles.push({
                startX: Math.random() * canvas.width,
                startY: Math.random() * canvas.height,
                startZ: Math.random() * 50 - 25,
                endX: x * 20,
                endY: y * 20,
                endZ: z * 20,
                currentX: 0,
                currentY: 0,
                currentZ: 0,
                size: Math.random() * 2 + 1
            });
        }

        function rotate3D(p, angleY) {
            const cosY = Math.cos(angleY);
            const sinY = Math.sin(angleY);

            const x = p.currentX * cosY - p.currentZ * sinY;
            const z = p.currentZ * cosY + p.currentX * sinY;

            return { x, y: p.currentY, z };
        }

        function animate(timestamp) {
            if (!startTime) startTime = timestamp;
            const progress = Math.min((timestamp - startTime) / transitionDuration, 1);

            ctx.clearRect(0, 0, canvas.width, canvas.height);

            angle += 0.01;

            particles.forEach(p => {
                p.currentX = p.startX + (p.endX - p.startX) * progress;
                p.currentY = p.startY + (p.endY - p.startY) * progress;
                p.currentZ = p.startZ + (p.endZ - p.startZ) * progress;

                const rotated = rotate3D(p, angle);

                const scale = 500 / (500 + rotated.z);
                const x2d = rotated.x * scale + canvas.width / 2;
                const y2d = rotated.y * scale + canvas.height / 2;

                ctx.beginPath();
                ctx.arc(x2d, y2d, p.size * scale, 0, Math.PI * 2);
                ctx.fillStyle = 'white';
                ctx.fill();
            });

            requestAnimationFrame(animate);
        }

        requestAnimationFrame(animate);
    </script>
</body>
</html>
